home *** CD-ROM | disk | FTP | other *** search
/ Risc World 3 / Risc World 3.iso / SOFTWARE / ISSUE6 / PD / PDF / GuiLib / GuiFlex / c++ / GuiFlexDA < prev    next >
Text File  |  2003-02-14  |  7KB  |  296 lines

  1. //--------------------------------------------------------------------------
  2. //
  3. //   Copyright (c) 2002, Colin Granville
  4. //
  5. //   All rights reserved.
  6. //
  7. //   Redistribution and use in source and binary forms, with or
  8. //   without modification, are permitted provided that the following 
  9. //   conditions are met:
  10. //
  11. //      * Redistributions of source code must retain the above copyright 
  12. //        notice, this list of conditions and the following disclaimer.
  13. //
  14. //      * Redistributions in binary form must reproduce the above 
  15. //        copyright notice, this list of conditions and the following 
  16. //        disclaimer in the documentation and/or other materials 
  17. //        provided with the distribution.
  18. //
  19. //      * The name Colin Granville may not be used to endorse or promote 
  20. //        products derived from this software without specific prior 
  21. //        written permission.
  22. //
  23. //   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
  24. //   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
  25. //   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
  26. //   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
  27. //   COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
  28. //   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
  29. //   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
  30. //   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
  31. //   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
  32. //   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  33. //   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
  34. //   OF THE POSSIBILITY OF SUCH DAMAGE.
  35. //
  36. //--------------------------------------------------------------------------
  37.  
  38. #include "GuiFlexDA.h"
  39. #include "fstream.h"
  40. #include "swis.h"
  41. #include <string.h>
  42.  
  43. inline int    align(int n)                                           {return ((n+3)&~3);}
  44. inline int    objectdif(GuiFlexDA::Object* a,GuiFlexDA::Object* b)   {return ((char*)a) - ((char*)b);}
  45.  
  46.  
  47. GuiFlexDA::GuiFlexDA(const char *name, int* /*error_fd*/, int dynamic_size)
  48.  : base(0),
  49.    top(0),
  50.    end(0)
  51. {
  52.   _swix(OS_DynamicArea,_INR(0,8)| _OUT(1) | _OUT(3) | _OUT(5),
  53.         0,
  54.         -1,
  55.         0,
  56.         -1,
  57.         (1<<7),
  58.         dynamic_size,
  59.         0,
  60.         0,
  61.         (name ? name:"GuiFlexDA"),
  62.         &number,
  63.         &base,
  64.         &maxSize
  65.        );
  66. }
  67.  
  68. //**************************************************************
  69.  
  70. GuiFlexDA::~GuiFlexDA()
  71. {
  72.   atExit();
  73. }
  74.  
  75. //**************************************************************
  76.  
  77. inline GuiFlexDA::Object* GuiFlexDA::nextObject(GuiFlexDA::Object* ob)
  78. {
  79.   return (GuiFlexDA::Object*)( ((char*)ob)+ob->capacity()+sizeof(GuiFlexDA::Object) );
  80. }
  81.  
  82. //**************************************************************
  83.  
  84. inline GuiFlexDA::Object* GuiFlexDA::topObject()
  85. {
  86.   return (GuiFlexDA::Object*)(base+top);
  87. }
  88.  
  89. //**************************************************************
  90.  
  91. inline GuiFlexDA::Object* GuiFlexDA::getObject(const GuiFlexAnchor& anchor) const
  92. {
  93.   Object* ob=0;
  94.   if (isOk() && 
  95.       ((size_t)anchor.data & 3)==0 &&
  96.       anchor.data>base && anchor.data< base+end )
  97.   {
  98.     ob=((Object*)anchor.data)-1;
  99.     if (ob->anchor != &anchor) ob=0;
  100.   }
  101.   return ob;
  102. }
  103.  
  104. //**************************************************************
  105.  
  106. inline void GuiFlexDA::setAnchor(GuiFlexAnchor& anchor,Object* object)
  107. {
  108.   anchor.data=(char*)(object+1);
  109.   object->anchor=&anchor;
  110. }
  111.  
  112. //**************************************************************
  113.  
  114. void GuiFlexDA::reanchor(Object* from)
  115. {
  116.   Object* to = topObject();
  117.   while (from!=to)
  118.   {
  119.     from->anchor->data=(char*)(from+1);
  120.     from=nextObject(from);
  121.   }
  122. }
  123.  
  124. //**************************************************************
  125.  
  126. bool GuiFlexDA::resize(size_t new_size)
  127. {
  128.   if (!isOk() && new_size>maxSize) return 0;
  129.   new_size=align(new_size);
  130.   int by=new_size-end;
  131.   int moved=0;
  132.   if (_swix(OS_ChangeDynamicArea,_INR(0,1)|_OUT(1),number,by,&moved) ||
  133.       (moved==0 && by>0) ) return 0;
  134.   if (by>0) end+=moved; else end-=moved;
  135.   return 1;
  136. }
  137.  
  138.  
  139. //**************************************************************
  140.  
  141. bool GuiFlexDA::alloc(GuiFlexAnchor& anchor,size_t n)
  142. {
  143.   if (!isOk()) return 0;
  144.  
  145.   size_t new_top = top+align(n+sizeof(Object));
  146.   if (new_top>end && !resize(new_top)) return 0;
  147.   Object* ob = topObject();
  148.   top=new_top;
  149.   ob->size=n;
  150.   setAnchor(anchor,ob);
  151.   return 1;
  152. }
  153.  
  154. //**************************************************************
  155.  
  156. bool GuiFlexDA::free(GuiFlexAnchor& anchor)
  157. {
  158.   Object* ob=getObject(anchor);
  159.   if (ob==0) return 0;
  160.   Object* next=nextObject(ob);
  161.   memmove(ob,next,objectdif(topObject(),next));
  162.   top+=objectdif(ob,next);
  163.   reanchor(ob);
  164.   resize(top);
  165.   anchor.data=0;
  166.   return 1;
  167. }
  168.  
  169. //**************************************************************
  170.  
  171. size_t GuiFlexDA::size(const GuiFlexAnchor& anchor) const
  172. {
  173.   Object* ob=getObject(anchor);
  174.   return ob==0 ? 0 : ob->size;
  175. }
  176.  
  177. //**************************************************************
  178.  
  179. bool GuiFlexDA::extend(GuiFlexAnchor& anchor,size_t new_size)
  180. {
  181.   Object* ob=getObject(anchor);
  182.   if (ob==0) return 0;
  183.  
  184.   int by=align(new_size-ob->capacity());
  185.  
  186.   if (by==0)
  187.   {
  188.     ob->size=new_size;
  189.     return 1;
  190.   }
  191.   
  192.   if (by>0)
  193.   {
  194.     if (!resize(top+by)) return 0;
  195.     Object* next=nextObject(ob);
  196.     memmove(((char*)next)+by,next,objectdif(topObject(),next));
  197.   }
  198.   else
  199.   {
  200.     Object* next=nextObject(ob);
  201.     memmove(((char*)next)+by,next,objectdif(topObject(),next));
  202.     if (!resize(top+by)) return 0;
  203.   }
  204.  
  205.   ob->size=new_size;
  206.   top+=by;
  207.   reanchor(nextObject(ob));
  208.   return 1;
  209. }
  210.  
  211. //**************************************************************
  212.  
  213. bool GuiFlexDA::midExtend(GuiFlexAnchor& anchor,size_t at,int by)
  214. {
  215.   Object* ob=getObject(anchor);
  216.   if (ob==0) return 0;
  217.   
  218.   if (by==0) return 1;
  219.  
  220.   if (at>=ob->size)
  221.   {
  222.     if (by<0 && at<-by) by=-at;
  223.     return extend(anchor,at+by);
  224.   }
  225.  
  226.   if (by>0)
  227.   {
  228.     if (!extend(anchor,ob->size+by)) return 0;
  229.     memmove(anchor.data+at+by,anchor.data+at,ob->size-at-by);
  230.   }
  231.   else
  232.   {
  233.     memmove(anchor.data+at+by,anchor.data+at,ob->size-at);
  234.     extend(anchor,ob->size+by);
  235.   }
  236.   return 1;
  237. }
  238.  
  239. //**************************************************************
  240.  
  241. bool GuiFlexDA::reanchor(GuiFlexAnchor& to, GuiFlexAnchor& from)
  242. {
  243.   Object* ob=getObject(from);
  244.   if (ob==0) return 0;
  245.   setAnchor(to,ob);
  246.   from.data=0;
  247.   return 1;
  248. }
  249.  
  250. //**************************************************************
  251.  
  252. bool GuiFlexDA::setBudge(bool on)
  253. {
  254.   return on;
  255. }
  256.  
  257. //**************************************************************
  258.  
  259. void GuiFlexDA::saveHeapInfo(char* filename) 
  260. {
  261.   ofstream out(filename);
  262.   if (!out) return;
  263.   out << "GuiFlexDA::saveHeapInfo not implemented" << endl;
  264. }
  265.  
  266. //**************************************************************
  267.  
  268. bool GuiFlexDA::compact()
  269. {
  270.   return 0;
  271. }
  272.  
  273. //**************************************************************
  274.  
  275. bool GuiFlexDA::setDeferredCompaction(bool on)
  276. {
  277.   return on;
  278. }
  279.  
  280. //**************************************************************
  281.  
  282. size_t GuiFlexDA::availableMemory()
  283. {
  284.   size_t freesize=0;
  285.   _swix(Wimp_SlotSize,_INR(0,1) | _OUT(2),-1,-1,&freesize);
  286.   if (freesize+end > maxSize) freesize=maxSize-end;
  287.   return (freesize+end-top);
  288. }
  289.  
  290. //**************************************************************
  291.  
  292. void GuiFlexDA::atExit()
  293. {
  294.   if (base) _swix(OS_DynamicArea,_INR(0,1),1,number);
  295. }
  296.